#ifndef CLIENT_DEPS_H_
#define CLIENT_DEPS_H_

#include <cstdlib>
#include <list>
#include <string>
#include <vector>

#include <pthread.h>

#include "observer.h"

using std::string;
using std::list;
using std::vector;

/**
 * Stores the dependency information of a particular file. It implements the
 * Observer and Subject interface. 
 */
class Deps : public Subject, public Observer {

  public:
    Deps(string file_name);
    Deps(string file_name, long file_size);
    virtual ~Deps();

    void Init();

    friend bool operator<(Deps &lhs, Deps &rhs);

    // Implementation of Observer's virtual methods
    virtual void Update(UpdateInfo update_info);

    // Implementation of Subject's virtual methods
    virtual void RegisterObserver(Observer *o);
    virtual void RemoveObserver(Observer *o);
    virtual void NotifyObservers();

    // Function call to indicate that this job has finished execution 
    void FinishExecution();

    void ScheduleTarget();

    // A list of dependencies of this file
    vector<Deps*> dependencies_;
    // Pointer to the next dependency of this file
    //Deps* next_;

    inline const long filesize();
    inline void set_file_size(long file_size);
    inline string filename();
    inline double exec_time();
    inline string priority();
    inline void set_priority(string priority);
    inline void set_exec_time(double exec_time);
    inline void set_heuristic_time(double heuristic_time);
    inline double heuristic_time();
    inline bool execution_done();

  private:
    string file_name_;
    long file_size_;
    int completed_deps_counter_;
    double heuristic_time_;
    bool exec_done_;
    double exec_time_; // In secs

    list<Observer *> observers_;
    UpdateInfo::UpdateType update_type_;
    pthread_mutex_t node_lock_;
    string prio_;
};

inline const long Deps::filesize() {
  return this->file_size_;
}

inline string Deps::filename() {
  return file_name_;
}

inline double Deps::exec_time() {
  return exec_time_;
}

inline string Deps::priority() {
  return prio_;
}

inline void Deps::set_priority(string priority) {
  prio_ = priority;
}

inline void Deps::set_exec_time(double exec_time) {
  exec_time_ = exec_time;
}

inline void Deps::set_heuristic_time(double heuristic_time) {
  heuristic_time_ = heuristic_time;
}

inline double Deps::heuristic_time() {
  return heuristic_time_;
}

inline bool Deps::execution_done() {
  return exec_done_;
}

inline void Deps::set_file_size(long file_size) {
  this->file_size_ = file_size;
}

#endif  // CLIENT_DEPS_H_
